package com.sina.shop.manage.service.goods;

import com.sina.shop.core.exception.client.DataException;
import com.sina.shop.core.exception.server.CreateException;
import com.sina.shop.core.exception.server.ResourceExistsException;
import com.sina.shop.core.exception.server.UpdateException;
import com.sina.shop.domain.business.Business;
import com.sina.shop.domain.goods.Goods;
import com.sina.shop.domain.menu.Menu;
import com.sina.shop.manage.dao.business.BusinessManageDao;
import com.sina.shop.manage.dao.goods.GoodsManageDao;
import com.sina.shop.manage.dao.menu.MenuManageDao;
import com.sina.shop.service.ShopDataSourceService;
import com.sina.shop.util.Assert;
import com.sina.shop.util.ResultCode;
import com.sina.shop.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

import static com.sina.shop.service.ServiceConstant.SHOP_TX;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * 段浩杰   2018-01-11-14:49
 */
@Service("goodsManageService")
public class GoodsManageServiceImpl extends ShopDataSourceService implements GoodsManageService {

    @Autowired
    @Qualifier("goodsManageDao")
    private GoodsManageDao goodsManageDao;

    @Autowired
    @Qualifier("businessManageDao")
    private BusinessManageDao businessManageDao;

    @Autowired
    @Qualifier("menuManageDao")
    private MenuManageDao menuManageDao;

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public List<Map<String, Object>> getGoodsIdAndName() {
        return goodsManageDao.getGoodsIdAndName();
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public List<Goods> getGoodsByAdminAccount(String account) {
        return goodsManageDao.getGoodsByAdminAccount(account);
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public Goods getGoodsById(Long id) {
        return goodsManageDao.get(Goods.class, id);
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public int deleteGoods(Long id) throws DataException, UpdateException {
        Goods goods = goodsManageDao.get(Goods.class, id);
        Assert.assertNotNull(goods, "Goods[id=%s] not exists", goods.getId());

        try {
            return goodsManageDao.deleteGoods(id);
        } catch (DataAccessException e) {
            LOG.error(" {} delete Goods error.", Goods.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.READ_COMMITTED)
    public Goods saveGoods(Goods goods) throws CreateException, ResourceExistsException, DataException {
        boolean exists;
        exists = goodsManageDao.isExistsByUnique(Goods.class, "name", goods.getName());
        Assert.assertFalse(exists, ResourceExistsException.class, ResultCode.dataExists
                , "Goods[%s] exists", goods.getName());

        try {
            goodsManageDao.save(goods);
            goodsManageDao.flush();
            return goods;
        } catch (DataAccessException e) {
            LOG.error(" {} save Goods error.", Goods.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    @Override
    @Transactional(value = SHOP_TX, isolation = Isolation.REPEATABLE_READ)
    public Goods updateGoods(Goods goods) throws UpdateException, DataException {
        Goods g = goodsManageDao.get(Goods.class, goods.getId());
        Assert.assertNotNull(g, "Goods[id=%s] not exists", goods.getId());

        try {
            g = updateGoodsFiled(goods, g);
            goodsManageDao.flush();

            return g;
        } catch (DataAccessException e) {
            LOG.error(" {} update Goods error.", Goods.class, e);
            throw new UpdateException(ResultCode.dataAccessError, e.getMessage(), e);
        }
    }

    private Goods updateGoodsFiled(Goods oldGoods, Goods newGoods) {

        if (!StringUtils.isEmpty(oldGoods.getName())) {
            newGoods.setName(newGoods.getName());
        }
        if (oldGoods.getBusiness() != null) {
            newGoods.setBusiness(oldGoods.getBusiness());
        }
        if (oldGoods.getMenu() != null) {
            newGoods.setMenu(oldGoods.getMenu());
        }
        if (oldGoods.getSum() != null) {
            newGoods.setSum(oldGoods.getSum());
        }
        if (oldGoods.getPrice() != null) {
            newGoods.setPrice(oldGoods.getPrice());
        }
        if (oldGoods.getRealPrice() != null) {
            newGoods.setRealPrice(oldGoods.getRealPrice());
        }
        if (oldGoods.getCredit() != null) {
            newGoods.setCredit(oldGoods.getCredit());
        }

        if (!StringUtils.isEmpty(oldGoods.getDescription())) {
            newGoods.setDescription(oldGoods.getDescription());
        }
        if (!StringUtils.isEmpty(oldGoods.getIsGroom())) {
            newGoods.setIsGroom(oldGoods.getIsGroom());
        }
        if (!StringUtils.isEmpty(oldGoods.getStatus())) {
            newGoods.setStatus(oldGoods.getStatus());
        }

        return newGoods;
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public List<Map<String, Object>> getGoodsList(Goods goods, Long[] count) {

        Business business = null;
        if (goods.getBusiness() != null && !StringUtils.isEmpty(goods.getBusiness().getName())) {

            business = businessManageDao.getBusinessByName(goods.getBusiness().getName());
            if (business == null) {
                business = new Business();
            }
        }
        goods.setBusiness(business);


        Menu menu = null;
        if (goods.getMenu() != null && !StringUtils.isEmpty(goods.getMenu().getName())) {

            menu = menuManageDao.getMenuByName(goods.getMenu().getName());
            if (menu == null) {
                menu = new Menu();
            }
        }
        goods.setMenu(menu);


        if (count != null && count.length > 0) {
            count[0] = goodsManageDao.getGoodsCount(goods);
        }

        return goodsManageDao.getGoodsList(goods);
    }

    @Override
    @Transactional(value = SHOP_TX, readOnly = true, isolation = Isolation.READ_COMMITTED)
    public List<Goods> getGoodsList() {
        return goodsManageDao.getGoodsList();
    }
}
